package com.xh.pmo.db;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.xh.pmo.domain.Team;

public class Query {
	private Connection conn = null;
	private PreparedStatement pstmt=null;
	private ResultSet rs=null;
	private Class clazz ;
	
	private String sql  = "";
	private List<Object> parameters = new ArrayList<Object>();
	private List<Object[]> parameterList = new ArrayList<Object[]>();
	
	public Query(Connection conn, String sql) {
		this.conn = conn;
		this.sql = sql; 
	}
	
	
	
	
	public Query setParameter (int i, Object obj) {
		parameters.add(i, obj);
		
		return this;
	}
	
	
	
	public Object uniqueResult (Class clazz) {
		this.clazz = clazz;
		
		Object obj  = null;
		try {
			pstmt = conn.prepareStatement(sql);
			for(int i=0; i<parameters.size(); i++) {
				pstmt.setObject(i+1, parameters.get(i));
			}
			rs = pstmt.executeQuery();
			
			obj = populateObj(rs,this.clazz);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return obj;
	}
	
	public List list(Class clazz) {
		this.clazz = clazz;
		List list = null;
		
		try {
			pstmt = conn.prepareStatement(sql);
			for(int i=0; i<parameters.size(); i++) {
				pstmt.setObject(i+1, parameters.get(i));
			}
			rs = pstmt.executeQuery();
			
			list = populateList(rs);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
		
	}
	
	
	private List<Object> populateList(ResultSet rs) throws Exception {
		ResultSetMetaData metaData = rs.getMetaData();
		int colCount = metaData.getColumnCount();
		List<Object> ret = new ArrayList<Object>();
		Field[] fields = clazz.getDeclaredFields();
		while (rs.next()) {
			Object newInstance = clazz.newInstance();
			
			for (int i = 1; i <= colCount; i++) {
				String columnName = metaData.getColumnName(i);
			//	System.out.println("columnName = " + columnName);
				
				try {
					Object value = rs.getObject(i);
					for (int j = 0; j < fields.length; j++) {
						Field f = fields[j];
						String fName=f.getName().toLowerCase();
						String fType = f.getType().getName();
						
						if(fType.equals("java.util.Set")) {
							continue;
						}
						
						String metaName=metaData.getColumnName(i).toLowerCase();
						if (metaName.endsWith("id") && metaName.length() > 2) {
							metaName = metaName.substring(0,metaName.length() - 2);
						}
						
						if (fName.equalsIgnoreCase(metaName)) {
							if (value != null) {
								//如果是基本数据类型  则直接风装bean
								if(isDateType(f)){
									f.set(newInstance, value);
									//System.out.println(columnName+" 不是一个引用类型");
								} else if(columnName.endsWith("Id")) {
									String newColumnName = columnName.substring(0,columnName.length() -2 );
									//System.out.println("是引用类型需要在查询   设置值");
									if(f.getName().equals(newColumnName)) {
										f.set(newInstance, getEnityByIdAdnType(f.getType(),rs.getLong(i)));
									}
								}
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			ret.add(newInstance);
		}
		return ret;
	}
	private Object getEnityByIdAdnType(Class clazz, Long id) throws Exception {
		Object entity = clazz.newInstance();
		
		String sql = "SELECT * FROM " +clazz.getSimpleName() + " WHERE id="+id; 
		pstmt = conn.prepareStatement(sql);

		ResultSet rs = pstmt.executeQuery();
		ResultSetMetaData rsmd = rs.getMetaData();
		int column = rsmd.getColumnCount();//拿到resultSet返回多少列
		
		Object ent = populateObj(rs,clazz);
		
		System.out.println(sql);
		
		return ent;
	}
	

	/*
	 * 通过反射生成单个对象
	 * @param rs
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	protected Object populateObj(ResultSet rs, Class clazz) throws Exception {
		
		//System.out.println(clazz.getName());
		
		
		ResultSetMetaData metaData = rs.getMetaData();
		int colCount = metaData.getColumnCount();
		List<Object> ret = new ArrayList<Object>();
		Object obj =null;
		Field[] fields = clazz.getDeclaredFields();
		
//System.out.println(fields.length + "字段长度" );

		while (rs.next()) {
			Object newInstance = clazz.newInstance();
			
			for (int i = 1; i <= colCount; i++) {
				String columnName = metaData.getColumnName(i);
				
				try {
					Object value = rs.getObject(i);
					for (int j = 0; j < fields.length; j++) {
						Field f = fields[j];
						String fName=f.getName().toLowerCase();
						String fType = f.getType().getName();
						
						if(fType.equals("java.util.Set")) {
							continue;
						}
						
						String metaName=metaData.getColumnName(i).toLowerCase();
						if (metaName.endsWith("id") && metaName.length() > 2) {
							metaName = metaName.substring(0,metaName.length() - 2);
						}
						
						
						
						if (fName.equalsIgnoreCase(metaName)) {
							if (value != null) {
								//如果是基本数据类型  则直接风装bean
								if(isDateType(f)){
								//	System.out.println(columnName+" 不是一个引用类型");
									f.set(newInstance, value);
								} else if(columnName.endsWith("Id")) {
									String newColumnName = columnName.substring(0,columnName.length() -2 );
									//System.out.println(columnName + "是引用类型需要在查询   设置值");
									if(f.getName().equals(newColumnName)) {
										f.set(newInstance, getEnityByIdAdnType(f.getType(),rs.getLong(i)));
									}
								}
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			ret.add(newInstance);
			if(ret.size() > 0 ) {
				obj = ret.get(0);
			}
			
			
		}
		return obj;

	}
	
private boolean isDateType(Field field) {
		
		String fieldType = field.getType().getName();//获取当前最短的类型名称
		field.setAccessible(true);
		if(fieldType.equals("java.lang.String")) {
			return true;
		} else if(fieldType.equals("java.lang.Double") ||fieldType.equals("double")) {
			return true;
		} else if(fieldType.equals("int") || fieldType.equals("java.lang.Integer")) {
			return true;
		} else if(fieldType.equals("float") || fieldType.equals("java.lang.Float")) {
			return true;
		} else if(fieldType.equals("java.lang.Long") || fieldType.equals("long")) {
			return true;
		} else if(fieldType.equals("java.lang.Byte") || fieldType.equals("byte")) {
			return true;
		} else if(fieldType.equals("java.lang.Boolean") || fieldType.equals("boolean")) {
			return true;
		} else if(fieldType.equals("java.lang.Short") || fieldType.equals("short")) {
			return true;
		} else if(fieldType.equals("java.util.Date") ) {
			return true;
		}else {
			//不是 基础数据类型  而是引用类型
			return false;
			
		}
	}

	
	public String getSql () {
		
		return this.sql;
	}




	public int excuteUpdate() {
		int stauts = 0;
		try {
			pstmt = conn.prepareStatement(sql);
			for(int i=0; i<parameters.size(); i++) {
				pstmt.setObject(i+1, parameters.get(i));
			}
			stauts = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return stauts;
	}



	public static void main(String[] args) {
		test(new Team());
		
	}
	
	public static void test (Object bj) {
		
		//ParameterizedType pd = (ParameterizedType) bj.getClass().getGenericSuperclass();
		
	//	Class claz  = (Class)pd.getActualTypeArguments()[0];
		
		System.out.println(bj.getClass().getName());
	}
	public Query setParameterList(String name, Object[] objs) {
		int startInt = sql.indexOf(":" + name);
		if(startInt == -1) {
			return this;
		}
		String bigenSql = sql.substring(0,startInt);
		String endSql = sql.substring(startInt + name.length()  + 1,sql.length());
		StringBuffer sb = new StringBuffer();
		for(Object obj : objs) {
			sb.append("'"+obj+"',");
		}
		sb.deleteCharAt(sb.toString().lastIndexOf(","));
		this.sql = bigenSql + sb.toString() +  endSql;
		return this;
	}
	
	public Query setParameterList(String name, Collection objs) {
		int startInt = sql.indexOf(":" + name);
		if(startInt == -1) {
			return this;
		}
		String bigenSql = sql.substring(0,startInt);
		String endSql = sql.substring(startInt + name.length()  + 1,sql.length());
		StringBuffer sb = new StringBuffer();
		for(Object obj : objs) {
			sb.append("'"+obj+"',");
		}
		sb.deleteCharAt(sb.toString().lastIndexOf(","));
		this.sql = bigenSql + sb.toString() +  endSql;
		return this;
	}
	
}
